import type {DetectOverflowOptions,Middleware} from '@floating-ui/dom';
import {detectOverflow} from '@floating-ui/dom';
import {getMainPlacement} from './utils';

interface Options{
	apply(args:{
		availableWidth:number;
		availableHeight:number;
	}):void;
	shift:boolean;
}
export default function(options:Partial<Options&DetectOverflowOptions>):Middleware{
	return {
		name:'maxSize',
		options,
		fn(middlewareArguments){
			const {placement,rects,elements:{floating}}=middlewareArguments;
			const {apply,shift,...detectOverflowOptions}=options;
			const mainPlacement=getMainPlacement(placement);
			return detectOverflow(
				middlewareArguments,
				detectOverflowOptions
			).then((overflow) => {
				const isXDirection=['left','right'].indexOf(mainPlacement)>-1;
				const {offsetWidth:prevWidth,offsetHeight:prevHeight}=floating;
				return Promise.resolve(apply&&apply({
					availableWidth:isXDirection
						?rects.floating.width-overflow[mainPlacement]
						:rects.floating.width-(
							shift
								?overflow.left+overflow.right
								:Math.min(overflow.left,overflow.right)
						),
					availableHeight:isXDirection
						?rects.floating.height-(
							shift
								?overflow.top+overflow.bottom
								:Math.min(overflow.top,overflow.bottom)
						)
						:rects.floating.height-overflow[mainPlacement],
				})).then(() => {
					const {offsetWidth:nextWidth,offsetHeight:nextHeight}=floating;
					if(
						prevWidth!==nextWidth||
						prevHeight!==nextHeight
					){
						return {
							reset:{
								rects:true,
							},
						};
					}
					return {};
				});
			});

		},
	};
}